package com.cps116.friendstracker;

import java.io.IOException;
import java.io.InputStream;
import java.io.StringReader;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;

import org.apache.http.HttpResponse;
import org.apache.http.NameValuePair;
import org.apache.http.client.HttpClient;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.message.BasicNameValuePair;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.xml.sax.InputSource;

import android.app.Activity;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.AsyncTask;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemSelectedListener;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.Spinner;
import android.widget.TextView;
import android.widget.Toast;

import com.cps116.resource.HttpResponseDecoder;
import com.easy.facebook.android.apicall.FQL;

public class ProfileActivity extends BaseActivity {

	public static final String TAG = ProfileActivity.class.getSimpleName();
	private UserLocationUpdateReceiver locationReceiver;
	private IntentFilter locationUpdateFilter;

	@Override
	public void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.profileactivity_layout);

		// setup the data adapter for the item lists and display the update option
		Spinner timeUpdateOptionSpinner = (Spinner) findViewById(R.id.location_update_spinner);
		ArrayAdapter<CharSequence> adapter = ArrayAdapter.createFromResource(
				this, R.array.profile_update_option_array,
				android.R.layout.simple_spinner_item);
		adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
		timeUpdateOptionSpinner.setAdapter(adapter);
		timeUpdateOptionSpinner
				.setOnItemSelectedListener(new UpdateOptionListener(this));

		// set scrollable content :CHECK, see if this works...
		((TextView) findViewById(R.id.profile_activity_update_history_textview))
				.setScrollContainer(true);

		// register the buttonlistener
		Button setupButton = (Button) findViewById(R.id.profile_view_preference_button);
		setupButton.setOnClickListener(new OnClickListener() {

			public void onClick(View v) {
				// set up the prefActivity
				startActivity(new Intent(v.getContext(), PrefActivity.class));
			}
		});

		// //set up the user_id so that we don't get conflict later...
		// fetchUserId(facebookFQL);
		// pull the image and username from FQL
		FQL facebookFQL = ((FriendsTrackerApplication) getApplication())
				.getFacebookFQL();

		TextView textfield = (TextView) findViewById(R.id.profile_activity_username_textview);
		ImageView imageview = (ImageView) findViewById(R.id.profile_activity_icon_imageview);
		new ProfileFacebookDataPuller(imageview, textfield)
				.execute(facebookFQL);

		// here we simply need to get the user_id from FQL and the user the
		// user_id as the key
		TextView last_loc_textview = (TextView) findViewById(R.id.profile_activity_user_last_location_textview);
		TextView recent_history_textview = (TextView) findViewById(R.id.profile_activity_update_history_textview);
		String user_id = ((FriendsTrackerApplication) getApplication())
				.getFacebookUserId();
		new ProfileDatabaseLocationDataPuller(last_loc_textview,
				recent_history_textview, timeUpdateOptionSpinner, user_id)
				.execute(facebookFQL);

		// TODO setup broadcast listener for location updates...[dynamic list
		// update]
		// SETUP location receiver here!
		// set up the filter here too!
		locationUpdateFilter = new IntentFilter(
				"com.cps116.NEW_LOCATION_SIGNAL");
		locationReceiver = new UserLocationUpdateReceiver(this);
		registerReceiver(locationReceiver, locationUpdateFilter);
	}

	//
	// /**
	// * Fetch the user id...
	// */
	// private void fetchUserId(FQL fql) {
	//
	// try {
	// //get the user ID's from facebook... use post request to
	// String result_xml =
	// fql.fqlQuery("SELECT uid FROM user WHERE uid = me()");
	//
	// DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
	// DocumentBuilder db = dbf.newDocumentBuilder();
	// InputSource is = new InputSource();
	// is.setCharacterStream(new StringReader(result_xml));
	// Document myDom = db.parse(is);
	// Element root = myDom.getDocumentElement();
	//
	// String uid
	// =root.getElementsByTagName("uid").item(0).getFirstChild().getNodeValue();
	//
	// //we want to set the user_id to the application...this way we are sure
	// that facebook id is set
	// //up and we won't get a run time exception error.
	// ((FriendsTrackerApplication)getApplication()).setFaceUserId(uid);
	// }
	// catch(Exception e)
	// {
	// //this will set the user id to the
	// Log.d("ProfileActivity", "fetchUserId failed...");
	// }
	//
	// }

	@Override
	protected void onPause() {
		super.onPause();

		// turn off the location service listener for update
		unregisterReceiver(locationReceiver);
	}

	@Override
	protected void onResume() {
		super.onResume();

		// start the location service listener for update
		// add to to the list...
		registerReceiver(locationReceiver, locationUpdateFilter);
	}

	/**
	 * Update the Update Option spinner and reset the GPS
	 * 
	 */

	private class UpdateOptionListener implements OnItemSelectedListener {

		Activity activityCaller;
		Map<String, Long> timeConverter;
		public static final long CONVERTER_BASIS = 1000;

		public UpdateOptionListener(ProfileActivity profileActivity) {
			activityCaller = profileActivity;

			// setting up the time converter...too lazy to do any other way
			timeConverter = new HashMap<String, Long>();
			timeConverter.put("No update", new Long(0));
			timeConverter.put("10 seconds", new Long(10 * CONVERTER_BASIS));
			timeConverter.put("5 seconds", new Long(10 * CONVERTER_BASIS));
			timeConverter.put("30 seconds", new Long(30 * CONVERTER_BASIS));
			timeConverter.put("1 minute", new Long(60 * CONVERTER_BASIS));
			timeConverter.put("5 minutes", new Long(5 * 60 * CONVERTER_BASIS));
			timeConverter
					.put("10 minutes", new Long(10 * 60 * CONVERTER_BASIS));
			timeConverter
					.put("20 minutes", new Long(20 * 60 * CONVERTER_BASIS));
			timeConverter.put("1 hour", new Long(60 * 60 * CONVERTER_BASIS));
			timeConverter.put("5 hours",
					new Long(5 * 60 * 60 * CONVERTER_BASIS));
			timeConverter
					.put("1 day", new Long(24 * 60 * 60 * CONVERTER_BASIS));
		}

		public void onItemSelected(AdapterView<?> parent, View view, int index,
				long arg3) {

			String user_time_choice = parent.getItemAtPosition(index)
					.toString();

			// display the message that you have updated
			Toast.makeText(parent.getContext(),
					String.format("Current update time: %s", user_time_choice),
					Toast.LENGTH_LONG).show();

			// get the time intervals for update in milliseconds
			long user_time_milliseconds = timeConverter.get(user_time_choice)
					.longValue();
			// Log.d("ProfileActivity", "" + user_time_milliseconds);

			// convert the user_time_choice to string
			((FriendsTrackerApplication) getApplication())
					.startNewUserLocationUpdateServiceInterval(activityCaller,
							user_time_milliseconds);
		}

		public void onNothingSelected(AdapterView<?> view) {
			// do not change anything
		}
	}

	/**
	 * Fetch the previous five locations that the user You might want to do
	 * threading here..because you need to parse the user_id from facebok before
	 * you can secure a connection here!
	 */
	private class ProfileDatabaseLocationDataPuller extends
			AsyncTask<FQL, String, String[]> {

		private TextView lastLocationUpdateTextView;
		private TextView recentHistoryTextView;
		private Spinner timeUpdateOptionSpinner;
		private String user_id;

		public ProfileDatabaseLocationDataPuller(TextView last_loc_textview,
				TextView recent_history_textview,
				Spinner timeUpdateOptionSpinner, String user_id) {

			this.timeUpdateOptionSpinner = timeUpdateOptionSpinner;
			this.lastLocationUpdateTextView = last_loc_textview;
			this.user_id = user_id;
			this.recentHistoryTextView = recent_history_textview;
		}

		@Override
		protected String[] doInBackground(FQL... fql) {

			FQL facebookdb = fql[0];
			try {
				// get the user ID's from facebook... use post request to
				String result_xml = facebookdb
						.fqlQuery("SELECT uid FROM user WHERE uid = me()");

				DocumentBuilderFactory dbf = DocumentBuilderFactory
						.newInstance();
				DocumentBuilder db = dbf.newDocumentBuilder();
				InputSource is = new InputSource();
				is.setCharacterStream(new StringReader(result_xml));
				Document myDom = db.parse(is);
				Element root = myDom.getDocumentElement();

				String uid = root.getElementsByTagName("uid").item(0)
						.getFirstChild().getNodeValue();
				Log.d("ProfileActivity", "Retrieved User Id:" + uid);
				Log.d("testing", "user_id: " + user_id);

				HttpClient httpclient = new DefaultHttpClient();
				HttpPost httppost = new HttpPost(
						"http://dbcourse.cs.duke.edu/tnd6/FFQueries/pullrecentlocationinfo.php");

				try {
					// Add your data
					List<NameValuePair> nameValuePairs = new ArrayList<NameValuePair>(
							1);
					nameValuePairs.add(new BasicNameValuePair("userid", uid));
					httppost.setEntity(new UrlEncodedFormEntity(nameValuePairs));

					// Execute HTTP Post Request
					HttpResponse response = httpclient.execute(httppost);
					String response_data = HttpResponseDecoder
							.getResponseBody(response);
					Log.d("ProfileDatabaseLocationDataPuller", "response_data "
							+ response_data);

					if (response_data.equals("")) {
						response_data = "ThereIsNo;Location Information";
						Log.d("ProfileDatabaseLocationDataPuller",
								"wegotheresomehow");
						String[] nullresponse = new String[1];
						nullresponse[0] = response_data;
						return nullresponse;
					} else {
						Log.d("ProfiledatabaseLocationDataPuller",
								"Could this be what is messing up?");
						ArrayList<String> timelist = new ArrayList<String>();
						String timelistarray[];
						Pattern p = Pattern.compile("(.+?);(.+?);");
						Matcher m = p.matcher(response_data);
						// Log.d("ProfileDatabaseLocationDataPuller",
						// m.group(0));
						while (m.find()) {
						String s = m.group(0);
						timelist.add(s);
						}
						timelistarray = new String[timelist.size()];
						for(int i=0; i<timelistarray.length; i++)
						{
							timelistarray[i] = timelist.get(i);
						}
						// Temporarily Disabling
						
						/**
						 * 
						 * 
						 * HERE HERE HERE HERE HERE HERE HERE HERE HERE HERE HERE HERE HERE HEREHERE HERE HERE HERE HERE HERE HERE
						 * HERE HERE HERE HERE HERE HERE HEREHERE HERE HERE HERE HERE HERE HEREHERE HERE HERE HERE HERE HERE HERE
						 * HERE HERE HERE HERE HERE HERE HEREHERE HERE HERE HERE HERE HERE HEREHERE HERE HERE HERE HERE HERE HERE
						 * HERE HERE HERE HERE HERE HERE HEREHERE HERE HERE HERE HERE HERE HEREHERE HERE HERE HERE HERE HERE HERE
						 * HERE HERE HERE HERE HERE HERE HEREHERE HERE HERE HERE HERE HERE HEREHERE HERE HERE HERE HERE HERE HERE
						 * I would start by looking in the else clause below, because thats where I'm adding the multiple rows to the table. I think
						 * its breaking because there is a vertical line appended to the end of the sentence. 
						 * 
						 * 
						 *//*
						if (response_data.indexOf('|') == response_data
								.length() - 1) {
							timelist.add(response_data.substring(0,
									response_data.length() - 1));
							timelistarray = new String[timelist.size()];
							timelistarray[0] = timelist.get(0);
						} else {
							timelistarray = response_data.split("|");
							for(int i = 0; i<timelistarray.length; i++)
							{
								timelist.add(timelistarray[i]);
							}
						}*/

						return timelistarray;

					}

				} catch (Exception e) {
					Log.d("E", "E inside try");
					return null;
				}
			} catch (Exception e) {
				Log.d("E", "E ouside try");
				return null;
			}
		}

		@Override
		protected void onPostExecute(String[] result) {
			super.onPostExecute(result);
			for (int i = 0; i < result.length; i++) {
				if (result[i] == null || result[i].equals(""))
					break; // not sure how last split will pan out, so putting
							// this here just in case
				String[] timeandlocation = result[i].split(";");
				String time = timeandlocation[0];
				String location = timeandlocation[1];
				ProfileActivity.this.updateUserHistory(location, time);
			}
			// **UI updates CANNOT BE DONE in doInBackground
			// do all the UI updates here!

		}
	}

	/**
	 * Pull the facebook icon image, username and facebook id from FQL
	 * 
	 */
	private class ProfileFacebookDataPuller extends
			AsyncTask<FQL, String, Object[]> {

		private TextView userTextView;
		private ImageView userProfileImageView;

		public ProfileFacebookDataPuller(ImageView imageview, TextView textfield) {
			userTextView = textfield;
			userProfileImageView = imageview;
		}

		@Override
		protected Object[] doInBackground(FQL... fql) {

			FQL facebookdb = fql[0];
			try {
				String result_xml = facebookdb
						.fqlQuery("SELECT name, pic_square FROM user WHERE uid = me()");

				DocumentBuilderFactory dbf = DocumentBuilderFactory
						.newInstance();
				DocumentBuilder db = dbf.newDocumentBuilder();
				InputSource is = new InputSource();
				is.setCharacterStream(new StringReader(result_xml));
				Document myDom = db.parse(is);
				Element root = myDom.getDocumentElement();

				String name = root.getElementsByTagName("name").item(0)
						.getFirstChild().getNodeValue();
				String picsquare = root.getElementsByTagName("pic_square")
						.item(0).getFirstChild().getNodeValue();

				Log.d("Profile Activity", "Retrieved Name:" + name);
				Log.d("Profile Activity", "Retrieved Picture Location:"
						+ picsquare);

				try {
					Bitmap bitmap = BitmapFactory
							.decodeStream((InputStream) new URL(picsquare)
									.getContent());
					return new Object[] { name, bitmap };

				} catch (MalformedURLException e) {
					e.printStackTrace();
				} catch (IOException e) {
					e.printStackTrace();
				}

			} catch (Exception e) {

				return null;
			}
			return null;
		}

		@Override
		protected void onPostExecute(Object[] result) {

			if (result != null)
				userTextView.setText((String) result[0]);
			userProfileImageView.setImageBitmap((Bitmap) result[1]);

			super.onPostExecute(result);
		}

	}

	/**
	 * This is the listener class listens to updates from
	 * UserLocationUpdateService
	 * 
	 */
	private class UserLocationUpdateReceiver extends BroadcastReceiver {

		private ProfileActivity profileActivity;

		public UserLocationUpdateReceiver(ProfileActivity profileActivity) {
			this.profileActivity = profileActivity;
		}

		@Override
		public void onReceive(Context context, Intent intent) {

			// we just want to notify new data is present...
			// listening for any updates...
			// display a message for picking up the data
			Log.d("ProfileActivity",
					"UserLocationUpdateReceiver is receiving data streams");

			String address = intent.getStringExtra("new-address");
			String update_time = intent.getStringExtra("new-time");

			profileActivity.updateUserHistory(address, update_time);

		}
	}

	/**
	 * This class specifies how the data is to be updated
	 * 
	 * @param address
	 * @param update_time
	 */
	public void updateUserHistory(String address, String update_time) {
		TextView historyTextView = (TextView) findViewById(R.id.profile_activity_update_history_textview);
		long unixTime = Long.parseLong(update_time);
		long timeStamp = (long) unixTime * 1000;
		Date d = new Date(timeStamp);
		update_time = d.toString();
		// we just want to append the text here...
		StringBuilder bd = new StringBuilder(String.format("%s, %s\n", address,
				update_time));
		bd.append(historyTextView.getText());
		historyTextView.setText(bd.toString());

		// set the latest update to the current address
		TextView latestUpdateTextView = (TextView) findViewById(R.id.profile_activity_user_last_location_textview);
		latestUpdateTextView.setText(address);

	}

}